import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
import _ from 'lodash-es'

export type ColumnItem = {
  dataIndex: string
  key: string
  title: string
}

type Options = {
  // table表的列
  columns: ColumnItem[]
  // 表格数据
  dataSource: any[]
  // 工作簿名称
  workbookName?: string
  // 工作表名称
  worksheetName?: string
  // table表中需要过滤的字段
  filterColum?: string[]
}

const defaultOptions = {
  columns: [],
  dataSource: [],
  workbookName: 'excel',
  worksheetName: 'sheet1',
  filterColum: ['action']
}

export const exportExcel = (options: Options = defaultOptions) => {
  const { columns, dataSource, workbookName, worksheetName, filterColum } =
    _.merge(defaultOptions, options)

  // 需要导出的数据字段
  const column = _.filter(
    columns,
    (item: ColumnItem) =>
      !_.some(filterColum, (value) => _.includes(item.key, value))
  )
  // 导出数据的字段名称
  let titles = _.map(column, 'title')
  // 导出数据的key值
  let keys = _.map(column, 'key')
  let sheetColumns: { [key: string]: any } = _.zipObject(
    keys as string[],
    titles
  ) as Partial<ColumnItem>
  // 格式化后的column（用于渲染excel表头 => 列）
  const newFormatColums = _.map(_.keys(sheetColumns), (key) => ({
    header: _.upperFirst(sheetColumns[key]),
    key
  }))

  // 创建工作簿
  const workbook = new ExcelJS.Workbook()
  // 创建工作表
  const worksheet = workbook.addWorksheet(worksheetName)
  // 设置列
  worksheet.columns = newFormatColums
  // 设置表头样式
  setWorksheetHeader(worksheet)
  // 添加行
  let rows = worksheet.addRows(dataSource)
  // 设置内容数据样式
  setWorksheetRow(rows)
  // 导出excel
  workbook.xlsx.writeBuffer().then((data) => {
    const blob = new Blob([data], { type: '' })
    saveAs(blob, `${workbookName}.xlsx`)
  })
}

// 设置表头样式
const setWorksheetHeader = (worksheet: ExcelJS.Worksheet) => {
  let headerRow = worksheet.getRow(1)
  headerRow.eachCell((cell, _colNum) => {
    // 设置背景色
    cell.fill = {
      type: 'pattern',
      pattern: 'solid',
      fgColor: { argb: 'dff8ff' }
    }
    // 设置字体
    cell.font = {
      bold: true,
      italic: true,
      size: 12,
      name: '微软雅黑',
      color: { argb: 'ff0000' }
    }
    // 设置对齐方式
    cell.alignment = {
      vertical: 'middle',
      horizontal: 'left',
      wrapText: false
    }
  })
}

// 设置数据内容样式
const setWorksheetRow = (rows?: any[]) => {
  rows?.forEach((row) => {
    // 设置字体
    row.font = {
      size: 11,
      name: '微软雅黑'
    }
    // 设置对齐方式
    row.alignment = {
      vertical: 'middle',
      horizontal: 'left',
      wrapText: false
    }
  })
}
